<script setup lang="ts">
import { onBeforeUnmount, ref, shallowRef, watch } from 'vue';
import { useVModel } from '@vueuse/core';
import '@wangeditor/editor/dist/css/style.css';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';

defineOptions({
  name: 'ReRichEditor'
});

interface Props {
  modelValue: string;
  height?: string;
  mode?: 'default' | 'simple';
  placeholder?: string;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  height: '300px',
  mode: 'default',
  placeholder: '请输入内容...'
});

const emit = defineEmits(['update:modelValue', 'change']);

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef();

// 内部值模型，双向绑定
const valueModel = useVModel(props, 'modelValue', emit);

// 编辑器配置
const editorConfig = {
  placeholder: props.placeholder,
  autoFocus: false,
  MENU_CONF: {
    // 图片上传配置
    uploadImage: {
      // 服务端地址
      server: '/api/upload/image',
      // 小于该值就插入 base64 格式（单位 kb）
      base64LimitSize: 5 * 1024,
      // 自定义上传
      customUpload(file: File, insertFn: any) {
        // 这里实现自定义上传
        // 如果需要自定义上传逻辑，可以在这里实现
        // 例如使用Element Plus的上传组件
        // 上传成功后调用insertFn插入图片
        console.log('customUpload', file);
        // 模拟上传成功
        setTimeout(() => {
          // 插入图片到编辑器
          insertFn('http://example.com/image.png', '图片名称', '图片描述');
        }, 1000);
      }
    },
    // 视频上传配置
    uploadVideo: {
      // 服务端地址
      server: '/api/upload/video',
      // 自定义上传
      customUpload(file: File, insertFn: any) {
        console.log('customUpload video', file);
        // 模拟上传成功
        setTimeout(() => {
          // 插入视频到编辑器
          insertFn('http://example.com/video.mp4');
        }, 1000);
      }
    }
  }
};

// 工具栏配置
const toolbarConfig = {
  // 默认模式下所有工具栏都显示
  // simple模式只显示基础的工具栏
  toolbarKeys: props.mode === 'simple' ? [
    'bold', 'italic', 'underline', 'through', 'justifyLeft', 'justifyCenter', 'justifyRight',
    'insertLink', 'bulletedList', 'numberedList'
  ] : [
    // 默认模式下的工具栏配置，提供更丰富的选项
    'headerSelect',
    'bold', 'italic', 'underline', 'through', 'fontSize', 'fontFamily', 'lineHeight',
    'color', 'bgColor',
    'justifyLeft', 'justifyCenter', 'justifyRight',
    'insertLink', 'bulletedList', 'numberedList', 'todo', 'emotion',
    'insertTable', 'insertImage', 'insertVideo', 'codeBlock', 'divider',
    'undo', 'redo'
  ]
};

// 编辑器内容
const editorHtml = ref(props.modelValue);

// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

// 监听传入的属性值变化
watch(() => props.modelValue, (newValue) => {
  if (editorHtml.value !== newValue) {
    editorHtml.value = newValue;
  }
});

// 处理编辑器内容变化
const handleChange = (editor) => {
  editorHtml.value = editor.getHtml();
  valueModel.value = editor.getHtml();
  emit('change', editor.getHtml());
};
</script>

<template>
  <div class="rich-editor">
    <Toolbar :editor="editorRef" :default-config="toolbarConfig" :mode="mode"
      :style="{ borderBottom: '1px solid #ccc' }" />
    <Editor v-model="editorHtml" :default-config="editorConfig" :mode="mode" :style="{ height, overflowY: 'hidden' }"
      @on-created="editorRef = $event" @onChange="handleChange" />
  </div>
</template>

<style scoped>
.rich-editor {
  border: 1px solid #ccc;
  border-radius: 4px;
}
</style>
